home *** CD-ROM | disk | FTP | other *** search
/ MacGames Sampler / PHT MacGames Bundle.iso / MacSource Folder / Samples from the CD / C and C++ / Gnuplot 3.5 for Macintosh / SOURCES 3.5 / misc.c < prev    next >
Text File  |  1993-11-12  |  27KB  |  1,005 lines

  1. #ifndef lint
  2. static char *RCSid = "$Id: misc.c%v 3.50 1993/07/09 05:35:24 woo Exp $";
  3. #endif
  4.  
  5.  
  6. /* GNUPLOT - misc.c */
  7. /*
  8.  * Copyright (C) 1986 - 1993   Thomas Williams, Colin Kelley
  9.  *
  10.  * Permission to use, copy, and distribute this software and its
  11.  * documentation for any purpose with or without fee is hereby granted, 
  12.  * provided that the above copyright notice appear in all copies and 
  13.  * that both that copyright notice and this permission notice appear 
  14.  * in supporting documentation.
  15.  *
  16.  * Permission to modify the software is granted, but not the right to
  17.  * distribute the modified code.  Modifications are to be distributed 
  18.  * as patches to released version.
  19.  *  
  20.  * This software is provided "as is" without express or implied warranty.
  21.  * 
  22.  *
  23.  * AUTHORS
  24.  *
  25.  *   Original Software:
  26.  *     Thomas Williams,  Colin Kelley.
  27.  * 
  28.  *   Gnuplot 2.0 additions:
  29.  *       Russell Lang, Dave Kotz, John Campbell.
  30.  *
  31.  *   Gnuplot 3.0 additions:
  32.  *       Gershon Elber and many others.
  33.  *
  34.  */
  35.  
  36. #include <stdio.h>
  37. #include <math.h>
  38. #ifndef THINK_C
  39. #ifndef __PUREC__
  40. #ifndef VMS
  41. #ifdef AMIGA_AC_5
  42. #include <exec/types.h>
  43. #else
  44. #include <sys/types.h>
  45. #endif /* AMIGA_AC_5 */
  46. #else
  47. #include <types.h>
  48. #endif
  49. #endif /* __PUREC__ */
  50. #else
  51. #include <types.h>
  52. #endif /* THINK_C */
  53.  
  54. #include "plot.h"
  55. #ifdef THINK_C
  56. #include "tout_protos.h"
  57. #endif
  58.  
  59. #include "setshow.h"
  60. #ifndef _Windows
  61. #include "help.h"
  62. #endif
  63.  
  64. #if !defined(__TURBOC__) && !defined (_IBMR2) && !defined (ATARI) && !defined (AMIGA_SC_6_1) && !defined(OSF1)
  65. #ifdef THINK_C
  66. extern void *malloc();
  67. extern void *realloc();
  68. char GPFAR *gpfaralloc(unsigned long size, char *message);
  69. char GPFAR * gpfarrealloc(char GPFAR *p, unsigned long size);
  70. void gpfarfree(char GPFAR *p);
  71.  
  72. #else
  73. extern char *malloc();
  74. extern char *realloc();
  75. #endif
  76. #endif
  77.  
  78. #if defined(__TURBOC__) && (defined(MSDOS) || defined(_Windows))
  79. #include <alloc.h>        /* for malloc, farmalloc, farrealloc */
  80. #endif
  81. #if defined(sequent)
  82. #include <sys/types.h>          /* typedef long size_t; */
  83. #endif
  84.  
  85. extern int c_token;
  86. extern char replot_line[];
  87. extern struct at_type at;
  88. extern struct ft_entry ft[];
  89. extern struct udft_entry *first_udf;
  90. extern struct udvt_entry *first_udv;
  91.  
  92. extern struct at_type *temp_at();
  93.  
  94. extern TBOOLEAN interactive;
  95. extern char *infile_name;
  96. extern int inline_num;
  97.  
  98. /* State information for load_file(), to recover from errors
  99.  * and properly handle recursive load_file calls
  100.  */
  101. typedef struct lf_state_struct LFS;
  102. struct lf_state_struct {
  103.     FILE *fp;                /* file pointer for load file */
  104.     char *name;            /* name of file */
  105.     TBOOLEAN interactive;        /* value of interactive flag on entry */
  106.     int inline_num;            /* inline_num on entry */
  107.     LFS *prev;                /* defines a stack */
  108. } *lf_head = NULL;            /* NULL if not in load_file */
  109.  
  110. static TBOOLEAN lf_pop();
  111. static void lf_push();
  112. FILE *lf_top();
  113.  
  114.  
  115. /*
  116.  * instead of <strings.h>
  117.  */
  118. #ifdef _Windows
  119. #include <string.h>
  120. #else
  121. #ifndef AMIGA_SC_6_1
  122. extern int strcmp();
  123. #endif /* !AMIGA_SC_6_1 */
  124. #endif
  125.  
  126. /* alloc:
  127.  * allocate memory 
  128.  * This is a protected version of malloc. It causes an int_error 
  129.  * if there is not enough memory, but first it tries FreeHelp() 
  130.  * to make some room, and tries again. If message is NULL, we 
  131.  * allow NULL return. Otherwise, we handle the error, using the
  132.  * message to create the int_error string. Note cp/sp_extend uses realloc,
  133.  * so it depends on this using malloc().
  134.  */
  135.  
  136. char *
  137. alloc(size, message)
  138.     unsigned long size;        /* # of bytes */
  139.     char *message;            /* description of what is being allocated */
  140. {
  141.     char *p;                /* the new allocation */
  142.     char errbuf[100];        /* error message string */
  143.  
  144. #ifdef THINK_C
  145.     p = (char *) malloc((size_t)size);
  146. #else
  147.     p = malloc((size_t)size);
  148. #endif
  149.     if (p == (char *)NULL) {
  150. #ifndef vms
  151. #ifndef _Windows
  152.        FreeHelp();            /* out of memory, try to make some room */
  153. #endif
  154. #endif
  155.        p = malloc((size_t)size);        /* try again */
  156.        if (p == (char *)NULL) {
  157.           /* really out of memory */
  158.           if (message != NULL) {
  159.              (void) sprintf(errbuf, "out of memory for %s", message);
  160.              int_error(errbuf, NO_CARET);
  161.              /* NOTREACHED */
  162.           }
  163.           /* else we return NULL */
  164.        }
  165.     }
  166.     return(p);
  167. }
  168.  
  169. /*
  170.  * cp_alloc() allocates a curve_points structure that can hold 'num'
  171.  * points.
  172.  */
  173. struct curve_points *
  174. cp_alloc(num)
  175.     int num;
  176. {
  177.     struct curve_points *cp;
  178.     cp = (struct curve_points *) alloc((unsigned long)sizeof(struct curve_points), "curve");
  179.     cp->p_max = (num >= 0 ? num : 0);
  180.     if (num > 0) {
  181.        cp->points = (struct coordinate GPHUGE *)
  182.         gpfaralloc((unsigned long)num * sizeof(struct coordinate), "curve points");
  183.     } else
  184.        cp->points = (struct coordinate GPHUGE *) NULL;
  185.     cp->next_cp = NULL;
  186.     cp->title = NULL;
  187.     return(cp);
  188. }
  189.  
  190.  
  191. /*
  192.  * cp_extend() reallocates a curve_points structure to hold "num"
  193.  * points. This will either expand or shrink the storage.
  194.  */
  195. cp_extend(cp, num)
  196.     struct curve_points *cp;
  197.     int num;
  198. {
  199.     struct coordinate GPHUGE *new;
  200.  
  201. #if (defined(MSDOS) || defined(_Windows))  &&  !defined(WIN32)
  202.     /* Make sure we do not allocate more than 64k points in msdos since 
  203.      * indexing is done with 16-bit int
  204.      * Leave some bytes for malloc maintainance.
  205.      */
  206.     if (num > 32700)
  207.         int_error("Array index must be less than 32k in msdos", NO_CARET);
  208. #endif /* MSDOS */
  209.  
  210.     if (num == cp->p_max) return(0);
  211.  
  212.     if (num > 0) {
  213.        if (cp->points == NULL) {
  214.           cp->points = (struct coordinate GPHUGE *)
  215.             gpfaralloc((unsigned long)num * sizeof(struct coordinate), "curve points");
  216.        } else {
  217.           new = (struct coordinate GPHUGE *)
  218. #ifdef THINK_C
  219.             gpfarrealloc((char GPFAR *)cp->points, (unsigned long)num * sizeof(struct coordinate));
  220. #else
  221.             gpfarrealloc(cp->points, (unsigned long)num * sizeof(struct coordinate));
  222. #endif
  223.           if (new == (struct coordinate GPHUGE *) NULL) {
  224.              int_error("No memory available for expanding curve points",
  225.                      NO_CARET);
  226.              /* NOTREACHED */
  227.           }
  228.           cp->points = new;
  229.        }
  230.        cp->p_max = num;
  231.     } else {
  232.        if (cp->points != (struct coordinate GPHUGE *) NULL)
  233. #ifdef THINK_C
  234.         gpfarfree((char GPFAR *)cp->points);
  235. #else
  236.         gpfarfree(cp->points);
  237. #endif
  238.        cp->points = (struct coordinate GPHUGE *) NULL;
  239.        cp->p_max = 0;
  240.     }
  241. }
  242.  
  243. /*
  244.  * cp_free() releases any memory which was previously malloc()'d to hold
  245.  *   curve points (and recursively down the linked list).
  246.  */
  247. cp_free(cp)
  248. struct curve_points *cp;
  249. {
  250.     if (cp) {
  251.         cp_free(cp->next_cp);
  252.         if (cp->title)
  253.             free((char *)cp->title);
  254.         if (cp->points)
  255.             gpfarfree((char *)cp->points);
  256.         free((char *)cp);
  257.     }
  258. }
  259.  
  260. /*
  261.  * iso_alloc() allocates a iso_curve structure that can hold 'num'
  262.  * points.
  263.  */
  264. struct iso_curve *
  265. iso_alloc(num)
  266.     int num;
  267. {
  268.     struct iso_curve *ip;
  269.     ip = (struct iso_curve *) alloc((unsigned long)sizeof(struct iso_curve), "iso curve");
  270.     ip->p_max = (num >= 0 ? num : 0);
  271.     if (num > 0) {
  272.        ip->points = (struct coordinate GPHUGE *)
  273.         gpfaralloc((unsigned long)num * sizeof(struct coordinate), "iso curve points");
  274.     } else
  275.        ip->points = (struct coordinate GPHUGE *) NULL;
  276.     ip->next = NULL;
  277.     return(ip);
  278. }
  279.  
  280. /*
  281.  * iso_extend() reallocates a iso_curve structure to hold "num"
  282.  * points. This will either expand or shrink the storage.
  283.  */
  284. iso_extend(ip, num)
  285.     struct iso_curve *ip;
  286.     int num;
  287. {
  288.     struct coordinate GPHUGE *new;
  289.  
  290.     if (num == ip->p_max) return(0);
  291.  
  292. #if (defined(MSDOS) || defined(_Windows))  &&  !defined(WIN32)
  293.     /* Make sure we do not allocate more than 64k points in msdos since 
  294.      * indexing is done with 16-bit int
  295.      * Leave some bytes for malloc maintainance.
  296.      */
  297.     if (num > 32700)
  298.         int_error("Array index must be less than 32k in msdos", NO_CARET);
  299. #endif /* MSDOS */
  300.  
  301.     if (num > 0) {
  302.        if (ip->points == NULL) {
  303.           ip->points = (struct coordinate GPHUGE *)
  304.             gpfaralloc((unsigned long)num * sizeof(struct coordinate), "iso curve points");
  305.        } else {
  306.           new = (struct coordinate GPHUGE *)
  307. #ifdef THINK_C
  308.             gpfarrealloc((char GPFAR *)ip->points, (unsigned long)num * sizeof(struct coordinate));
  309. #else
  310.             gpfarrealloc(ip->points, (unsigned long)num * sizeof(struct coordinate));
  311. #endif
  312.           if (new == (struct coordinate GPHUGE *) NULL) {
  313.              int_error("No memory available for expanding curve points",
  314.                      NO_CARET);
  315.              /* NOTREACHED */
  316.           }
  317.           ip->points = new;
  318.        }
  319.        ip->p_max = num;
  320.     } else {
  321.        if (ip->points != (struct coordinate GPHUGE *) NULL)
  322. #ifdef THINK_C
  323.         gpfarfree((char GPFAR *)ip->points);
  324. #else
  325.         gpfarfree(ip->points);
  326. #endif
  327.        ip->points = (struct coordinate GPHUGE *) NULL;
  328.        ip->p_max = 0;
  329.     }
  330. }
  331.  
  332. /*
  333.  * iso_free() releases any memory which was previously malloc()'d to hold
  334.  *   iso curve points.
  335.  */
  336. iso_free(ip)
  337. struct iso_curve *ip;
  338. {
  339.     if (ip) {
  340.         if (ip->points)
  341.             gpfarfree((char *)ip->points);
  342.         free((char *)ip);
  343.     }
  344. }
  345.  
  346. /*
  347.  * sp_alloc() allocates a surface_points structure that can hold 'num_iso_1'
  348.  * iso-curves with 'num_samp_2' samples and 'num_iso_2' iso-curves with
  349.  * 'num_samp_1' samples.
  350.  * If, however num_iso_2 or num_samp_1 is zero no iso curves are allocated.
  351.  */
  352. struct surface_points *
  353. sp_alloc(num_samp_1,num_iso_1,num_samp_2,num_iso_2)
  354.     int num_samp_1,num_iso_1,num_samp_2,num_iso_2;
  355. {
  356.     struct surface_points *sp;
  357.  
  358.     sp = (struct surface_points *) alloc((unsigned long)sizeof(struct surface_points), "surface");
  359.     sp->next_sp = NULL;
  360.     sp->title = NULL;
  361.     sp->contours = NULL;
  362.     sp->iso_crvs = NULL;
  363.     sp->num_iso_read = 0;
  364.  
  365.     if (num_iso_2 > 0 && num_samp_1 > 0) {
  366.     int i;
  367.     struct iso_curve *icrv;
  368.  
  369.     for (i = 0; i < num_iso_1; i++) {
  370.         icrv = iso_alloc(num_samp_2);
  371.         icrv->next = sp->iso_crvs;
  372.         sp->iso_crvs = icrv;
  373.     }
  374.     for (i = 0; i < num_iso_2; i++) {
  375.         icrv = iso_alloc(num_samp_1);
  376.         icrv->next = sp->iso_crvs;
  377.         sp->iso_crvs = icrv;
  378.     }
  379.     } else
  380.     sp->iso_crvs = (struct iso_curve *) NULL;
  381.  
  382.     return(sp);
  383. }
  384.  
  385. /*
  386.  * sp_replace() updates a surface_points structure so it can hold 'num_iso_1'
  387.  * iso-curves with 'num_samp_2' samples and 'num_iso_2' iso-curves with
  388.  * 'num_samp_1' samples.
  389.  * If, however num_iso_2 or num_samp_1 is zero no iso curves are allocated.
  390.  */
  391. sp_replace(sp,num_samp_1,num_iso_1,num_samp_2,num_iso_2)
  392.        struct surface_points *sp;
  393.        int num_samp_1,num_iso_1,num_samp_2,num_iso_2;
  394. {
  395.     int i;
  396.     struct iso_curve *icrv, *icrvs = sp->iso_crvs;
  397.  
  398.     while ( icrvs ) {
  399.     icrv = icrvs;
  400.     icrvs = icrvs->next;
  401.     iso_free( icrv );
  402.     }
  403.     sp->iso_crvs = NULL;
  404.     
  405.     if (num_iso_2 > 0 && num_samp_1 > 0) {
  406.     for (i = 0; i < num_iso_1; i++) {
  407.         icrv = iso_alloc(num_samp_2);
  408.         icrv->next = sp->iso_crvs;
  409.         sp->iso_crvs = icrv;
  410.     }
  411.     for (i = 0; i < num_iso_2; i++) {
  412.         icrv = iso_alloc(num_samp_1);
  413.         icrv->next = sp->iso_crvs;
  414.         sp->iso_crvs = icrv;
  415.     }
  416.     } else
  417.     sp->iso_crvs = (struct iso_curve *) NULL;
  418. }
  419.  
  420. /*
  421.  * sp_free() releases any memory which was previously malloc()'d to hold
  422.  *   surface points.
  423.  */
  424. sp_free(sp)
  425. struct surface_points *sp;
  426. {
  427.     if (sp) {
  428.         sp_free(sp->next_sp);
  429.         if (sp->title)
  430.             free((char *)sp->title);
  431.         if (sp->contours) {
  432.             struct gnuplot_contours *cntr, *cntrs = sp->contours;
  433.  
  434.             while (cntrs) {
  435.                 cntr = cntrs;
  436.                 cntrs = cntrs->next;
  437. #ifdef THINK_C
  438.                 gpfarfree((char GPFAR *)cntr->coords);
  439. #else
  440.                 gpfarfree(cntr->coords);
  441. #endif
  442.                 free(cntr);
  443.             }
  444.         }
  445.         if (sp->iso_crvs) {
  446.             struct iso_curve *icrv, *icrvs = sp->iso_crvs;
  447.  
  448.             while (icrvs) {
  449.                 icrv = icrvs;
  450.                 icrvs = icrvs->next;
  451.                 iso_free(icrv);
  452.             }
  453.         }
  454.         free((char *)sp);
  455.     }
  456. }
  457.  
  458.  
  459.  
  460. save_functions(fp)
  461. FILE *fp;
  462. {
  463. register struct udft_entry *udf = first_udf;
  464.  
  465.     if (fp) {
  466.         while (udf) {
  467.             if (udf->definition)
  468.                 fprintf(fp,"%s\n",udf->definition);
  469.             udf = udf->next_udf;
  470.         }
  471.         (void) fclose(fp);
  472.     } else
  473.         os_error("Cannot open save file",c_token);            
  474. }
  475.  
  476.  
  477. save_variables(fp)
  478. FILE *fp;
  479. {
  480. register struct udvt_entry *udv = first_udv->next_udv;    /* skip pi */
  481.  
  482.     if (fp) {
  483.         while (udv) {
  484.             if (!udv->udv_undef) {
  485.                 fprintf(fp,"%s = ",udv->udv_name);
  486.                 disp_value(fp,&(udv->udv_value));
  487.                 (void) putc('\n',fp);
  488.             }
  489.             udv = udv->next_udv;
  490.         }
  491.         (void) fclose(fp);
  492.     } else
  493.         os_error("Cannot open save file",c_token);            
  494. }
  495.  
  496.  
  497. save_all(fp)
  498. FILE *fp;
  499. {
  500. register struct udft_entry *udf = first_udf;
  501. register struct udvt_entry *udv = first_udv->next_udv;    /* skip pi */
  502.  
  503.     if (fp) {
  504.         save_set_all(fp);
  505.         while (udf) {
  506.             if (udf->definition)
  507.                 fprintf(fp,"%s\n",udf->definition);
  508.             udf = udf->next_udf;
  509.         }
  510.         while (udv) {
  511.             if (!udv->udv_undef) {
  512.                 fprintf(fp,"%s = ",udv->udv_name);
  513.                 disp_value(fp,&(udv->udv_value));
  514.                 (void) putc('\n',fp);
  515.             }
  516.             udv = udv->next_udv;
  517.         }
  518.         fprintf(fp,"%s\n",replot_line);
  519.         (void) fclose(fp);
  520.     } else
  521.         os_error("Cannot open save file",c_token);            
  522. }
  523.  
  524.  
  525. save_set(fp)
  526. FILE *fp;
  527. {
  528.     if (fp) {
  529.         save_set_all(fp);
  530.         (void) fclose(fp);
  531.     } else
  532.         os_error("Cannot open save file",c_token);            
  533. }
  534.  
  535.  
  536. save_set_all(fp)
  537. FILE *fp;
  538. {
  539. struct text_label *this_label;
  540. struct arrow_def *this_arrow;
  541. char *quote;
  542.     fprintf(fp,"set terminal %s %s\n", term_tbl[term].name, term_options);
  543.     fprintf(fp,"set output %s\n",strcmp(outstr,"STDOUT")? outstr : "" );
  544.     fprintf(fp,"set %sclip points\n", (clip_points)? "" : "no");
  545.     fprintf(fp,"set %sclip one\n", (clip_lines1)? "" : "no");
  546.     fprintf(fp,"set %sclip two\n", (clip_lines2)? "" : "no");
  547.     fprintf(fp,"set %sborder\n",draw_border ? "" : "no");
  548.     if (boxwidth<0.0)
  549.         fprintf(fp,"set boxwidth\n");
  550.     else
  551.         fprintf(fp,"set boxwidth %g\n",boxwidth);
  552.     if (dgrid3d)
  553.         fprintf(fp,"set dgrid3d %d,%d, %d\n",
  554.             dgrid3d_row_fineness,
  555.             dgrid3d_col_fineness,
  556.             dgrid3d_norm_value);
  557.  
  558.     fprintf(fp,"set dummy %s,%s\n",dummy_var[0], dummy_var[1]);
  559.     fprintf(fp,"set format x \"%s\"\n", xformat);
  560.     fprintf(fp,"set format y \"%s\"\n", yformat);
  561.     fprintf(fp,"set format z \"%s\"\n", zformat);
  562.     fprintf(fp,"set %sgrid\n", (grid)? "" : "no");
  563.     switch (key) {
  564.         case -1 :
  565.             fprintf(fp,"set key\n");
  566.             break;
  567.         case 0 :
  568.             fprintf(fp,"set nokey\n");
  569.             break;
  570.         case 1 :
  571.             fprintf(fp,"set key %g,%g,%g\n",key_x,key_y,key_z);
  572.             break;
  573.     }
  574.     fprintf(fp,"set nolabel\n");
  575.     for (this_label = first_label; this_label != NULL;
  576.             this_label = this_label->next) {
  577.         fprintf(fp,"set label %d \"%s\" at %g,%g,%g ",
  578.                this_label->tag,
  579.                this_label->text, this_label->x,
  580.                          this_label->y,
  581.                          this_label->z);
  582.         switch(this_label->pos) {
  583.             case LEFT :
  584.                 fprintf(fp,"left");
  585.                 break;
  586.             case CENTRE :
  587.                 fprintf(fp,"centre");
  588.                 break;
  589.             case RIGHT :
  590.                 fprintf(fp,"right");
  591.                 break;
  592.         }
  593.         fputc('\n',fp);
  594.     }
  595.     fprintf(fp,"set noarrow\n");
  596.     for (this_arrow = first_arrow; this_arrow != NULL;
  597.             this_arrow = this_arrow->next) {
  598.         fprintf(fp,"set arrow %d from %g,%g,%g to %g,%g,%g%s\n",
  599.                this_arrow->tag,
  600.                this_arrow->sx, this_arrow->sy, this_arrow->sz,
  601.                this_arrow->ex, this_arrow->ey, this_arrow->ez,
  602.                this_arrow->head ? "" : " nohead");
  603.     }
  604.     fprintf(fp,"set nologscale\n");
  605.     if (is_log_x) fprintf(fp,"set logscale x %g\n", base_log_x);
  606.     if (is_log_y) fprintf(fp,"set logscale y %g\n", base_log_y);
  607.     if (is_log_z) fprintf(fp,"set logscale z %g\n", base_log_z);
  608.     fprintf(fp,"set offsets %g, %g, %g, %g\n",loff,roff,toff,boff);
  609.     fprintf(fp,"set %spolar\n", (polar)? "" : "no");
  610.     fprintf(fp,"set angles %s\n", (angles_format == ANGLES_RADIANS)?
  611.                         "radians" : "degrees");
  612.     fprintf(fp,"set %sparametric\n", (parametric)? "" : "no");
  613.     fprintf(fp,"set view %g, %g, %g, %g\n",
  614.         surface_rot_x, surface_rot_z, surface_scale, surface_zscale);
  615.     fprintf(fp,"set samples %d, %d\n",samples_1,samples_2);
  616.     fprintf(fp,"set isosamples %d, %d\n",iso_samples_1,iso_samples_2);
  617.     fprintf(fp,"set %ssurface\n",(draw_surface) ? "" : "no");
  618.     fprintf(fp,"set %scontour",(draw_contour) ? "" : "no");
  619.     switch (draw_contour) {
  620.         case CONTOUR_NONE: fprintf(fp, "\n"); break;
  621.         case CONTOUR_BASE: fprintf(fp, " base\n"); break;
  622.         case CONTOUR_SRF:  fprintf(fp, " surface\n"); break;
  623.         case CONTOUR_BOTH: fprintf(fp, " both\n"); break;
  624.     }
  625.      fprintf(fp,"set %sclabel\n",(label_contours) ? "" : "no");
  626.     fprintf(fp,"set %shidden3d\n",(hidden3d) ? "" : "no");
  627.     fprintf(fp,"set cntrparam order %d\n", contour_order);
  628.     fprintf(fp,"set cntrparam ");
  629.     switch (contour_kind) {
  630.         case CONTOUR_KIND_LINEAR:    fprintf(fp, "linear\n"); break;
  631.         case CONTOUR_KIND_CUBIC_SPL: fprintf(fp, "cubicspline\n"); break;
  632.         case CONTOUR_KIND_BSPLINE:   fprintf(fp, "bspline\n"); break;
  633.     }
  634.     fprintf(fp,"set cntrparam levels ");
  635.     switch (levels_kind) {
  636.         int i;
  637.         case LEVELS_AUTO:
  638.             fprintf(fp, "auto %d\n", contour_levels);
  639.             break;
  640.         case LEVELS_INCREMENTAL:
  641.             fprintf(fp, "incremental %g,%g,%g\n",
  642.                 levels_list[0], levels_list[1], 
  643.                 levels_list[0]+levels_list[1]*contour_levels);
  644.             break;
  645.         case LEVELS_DISCRETE:
  646.             fprintf(fp, "discrete ");
  647.                 fprintf(fp, "%g", levels_list[0]);
  648.             for(i = 1; i < contour_levels; i++)
  649.                 fprintf(fp, ",%g ", levels_list[i]);
  650.             fprintf(fp, "\n");
  651.     }
  652.     fprintf(fp,"set cntrparam points %d\n", contour_pts);
  653.     fprintf(fp,"set size %g,%g\n",xsize,ysize);
  654.     fprintf(fp,"set data style ");
  655.     switch (data_style) {
  656.         case LINES: fprintf(fp,"lines\n"); break;
  657.         case POINTSTYLE: fprintf(fp,"points\n"); break;
  658.         case IMPULSES: fprintf(fp,"impulses\n"); break;
  659.         case LINESPOINTS: fprintf(fp,"linespoints\n"); break;
  660.         case DOTS: fprintf(fp,"dots\n"); break;
  661.         case ERRORBARS: fprintf(fp,"errorbars\n"); break;
  662.         case BOXES: fprintf(fp,"boxes\n"); break;
  663.         case BOXERROR: fprintf(fp,"boxerrorbars\n"); break;
  664.         case STEPS: fprintf(fp,"steps\n"); break;       /* JG */
  665.     }
  666.     fprintf(fp,"set function style ");
  667.     switch (func_style) {
  668.         case LINES: fprintf(fp,"lines\n"); break;
  669.         case POINTSTYLE: fprintf(fp,"points\n"); break;
  670.         case IMPULSES: fprintf(fp,"impulses\n"); break;
  671.         case LINESPOINTS: fprintf(fp,"linespoints\n"); break;
  672.         case DOTS: fprintf(fp,"dots\n"); break;
  673.         case ERRORBARS: fprintf(fp,"errorbars\n"); break;
  674.         case BOXES: fprintf(fp,"boxes\n"); break;
  675.         case BOXERROR: fprintf(fp,"boxerrorbars\n"); break;
  676.         case STEPS: fprintf(fp,"steps\n"); break;       /* JG */
  677.     }
  678.         fprintf(fp,"set %sxzeroaxis\n", (xzeroaxis)? "" : "no");
  679.         fprintf(fp,"set %syzeroaxis\n", (yzeroaxis)? "" : "no");
  680.         fprintf(fp,"set tics %s\n", (tic_in)? "in" : "out");
  681.         fprintf(fp,"set ticslevel %g\n", ticslevel);
  682.         save_tics(fp, xtics, 'x', &xticdef);
  683.         save_tics(fp, ytics, 'y', &yticdef);
  684.         save_tics(fp, ztics, 'z', &zticdef);
  685.         for (quote = &(title[0]); quote && *quote && (*quote != '"'); quote++)
  686.             ;
  687.         fprintf(fp,"set title %c%s%c %d,%d\n",*quote ? '\'' : '"',title,*quote ? '\'' : '"',title_xoffset,title_yoffset);
  688.     
  689.         if (timedate)
  690.         fprintf(fp,"set time %d,%d\n",time_xoffset,time_yoffset);
  691.     else
  692.         fprintf(fp,"set notime\n");
  693.      fprintf(fp,"set rrange [%g : %g]\n",rmin,rmax);
  694.     fprintf(fp,"set trange [%g : %g]\n",tmin,tmax);
  695.     fprintf(fp,"set urange [%g : %g]\n",umin,umax);
  696.     fprintf(fp,"set vrange [%g : %g]\n",vmin,vmax);
  697.         for (quote = &(xlabel[0]); quote && *quote && (*quote != '"'); quote++)
  698.             ;
  699.         fprintf(fp,"set xlabel %c%s%c %d,%d\n",*quote ? '\'' : '"',xlabel,*quote ? '\'' : '"',xlabel_xoffset,xlabel_yoffset);
  700.         fprintf(fp,"set xrange [%g : %g]\n",xmin,xmax);
  701.         for (quote = &(ylabel[0]); quote && *quote && (*quote != '"'); quote++)
  702.             ;
  703.         fprintf(fp,"set ylabel %c%s%c %d,%d\n",*quote ? '\'' : '"',ylabel,*quote ? '\'' : '"',ylabel_xoffset,ylabel_yoffset);
  704.         fprintf(fp,"set yrange [%g : %g]\n",ymin,ymax);
  705.         for (quote = &(zlabel[0]); quote && *quote && (*quote != '"'); quote++)
  706.             ;
  707.         fprintf(fp,"set zlabel %c%s%c %d,%d\n",*quote ? '\'' : '"',zlabel,*quote ? '\'' : '"',zlabel_xoffset,zlabel_yoffset);
  708.     fprintf(fp,"set zrange [%g : %g]\n",zmin,zmax);
  709.     fprintf(fp,"set %s %c\n", 
  710.         autoscale_r ? "autoscale" : "noautoscale", 'r');
  711.     fprintf(fp,"set %s %c\n", 
  712.         autoscale_t ? "autoscale" : "noautoscale", 't');
  713.     fprintf(fp,"set %s %c%c\n", 
  714.         (autoscale_y||autoscale_x) ? "autoscale" : "noautoscale", 
  715.         autoscale_x ? 'x' : ' ', autoscale_y ? 'y' : ' ');
  716.     fprintf(fp,"set %s %c\n", 
  717.         autoscale_z ? "autoscale" : "noautoscale", 'z');
  718.     fprintf(fp,"set zero %g\n",zero);
  719. }
  720.  
  721. #ifdef THINK_C
  722. save_tics(FILE *fp, TBOOLEAN onoff, char axis, struct ticdef *tdef)
  723. #else
  724. save_tics(fp, onoff, axis, tdef)
  725.     FILE *fp;
  726.     TBOOLEAN onoff;
  727.     char axis;
  728.     struct ticdef *tdef;
  729. #endif
  730. {
  731.     if (onoff) {
  732.        fprintf(fp,"set %ctics", axis);
  733.        switch(tdef->type) {
  734.           case TIC_COMPUTED: {
  735.              break;
  736.           }
  737.           case TIC_MONTH:{
  738.               fprintf(fp,"\nset %cmtics",axis);
  739.             break;
  740.           }
  741.             case TIC_DAY:{
  742.             fprintf(fp,"\nset %cdtics",axis);
  743.             break;
  744.             }
  745.           case TIC_SERIES: {
  746.                  if (tdef->def.series.end >= VERYLARGE)
  747.                  fprintf(fp, " %g,%g", tdef->def.series.start,
  748.                                         tdef->def.series.incr);
  749.                          else
  750.                  fprintf(fp, " %g,%g,%g", tdef->def.series.start,
  751.                                         tdef->def.series.incr, tdef->def.series.end);
  752.              break;
  753.           }
  754.           case TIC_USER: {
  755.              register struct ticmark *t;
  756.              fprintf(fp, " (");
  757.              for (t = tdef->def.user; t != NULL; t=t->next) {
  758.                 if (t->label)
  759.                   fprintf(fp, "\"%s\" ", t->label);
  760.                 if (t->next)
  761.                   fprintf(fp, "%g, ", t->position);
  762.                 else
  763.                   fprintf(fp, "%g", t->position);
  764.              }
  765.              fprintf(fp, ")");
  766.              break;
  767.           } 
  768.        }
  769.        fprintf(fp, "\n");
  770.     } else {
  771.        fprintf(fp,"set no%ctics\n", axis);
  772.     }
  773. }
  774.  
  775. load_file(fp, name)
  776.     FILE *fp;
  777.     char *name;
  778. {
  779.     register int len;
  780.     extern char input_line[];
  781.  
  782.     int start, left;
  783.     int more;
  784.     int stop = FALSE;
  785.  
  786.     lf_push(fp);            /* save state for errors and recursion */
  787.  
  788.     if (fp == (FILE *)NULL) {
  789.        char errbuf[BUFSIZ];
  790.        (void) sprintf(errbuf, "Cannot open load file '%s'", name);
  791.        os_error(errbuf, c_token);
  792.     } else {
  793.        /* go into non-interactive mode during load */
  794.        /* will be undone below, or in load_file_error */
  795.        interactive = FALSE;
  796.        inline_num = 0;
  797.        infile_name = name;
  798.  
  799.        while (!stop) {        /* read all commands in file */
  800.           /* read one command */
  801.           left = MAX_LINE_LEN;
  802.           start = 0;
  803.           more = TRUE;
  804.  
  805.           while (more) {
  806.              if (fgets(&(input_line[start]), left, fp) == (char *)NULL) {
  807.                 stop = TRUE; /* EOF in file */
  808.                 input_line[start] = '\0';
  809.                 more = FALSE;    
  810.              } else {
  811.                 inline_num++;
  812.                 len = strlen(input_line) - 1;
  813.                 if (input_line[len] == '\n') { /* remove any newline */
  814.                     input_line[len] = '\0';
  815.                     /* Look, len was 1-1 = 0 before, take care here! */
  816.                     if (len > 0) --len;
  817.                 } else if (len+1 >= left)
  818.                   int_error("Input line too long",NO_CARET);
  819.                  
  820.                 if (input_line[len] == '\\') { /* line continuation */
  821.                     start = len;
  822.                     left  = MAX_LINE_LEN - start; /* left -=len;*/
  823.                 } else
  824.                   more = FALSE;
  825.              }
  826.           }
  827.  
  828.           if (strlen(input_line) > 0) {
  829.              screen_ok = FALSE;    /* make sure command line is
  830.                                echoed on error */
  831.              do_line();
  832.           }
  833.        }
  834.     }
  835.  
  836.     /* pop state */
  837.     (void) lf_pop();        /* also closes file fp */
  838. }
  839.  
  840. /* pop from load_file state stack */
  841. static TBOOLEAN                /* FALSE if stack was empty */
  842. lf_pop()                    /* called by load_file and load_file_error */
  843. {
  844.     LFS *lf;
  845.  
  846.     if (lf_head == NULL)
  847.      return(FALSE);
  848.     else {
  849.        lf = lf_head;
  850.        if (lf->fp != (FILE *)NULL)
  851.         (void) fclose(lf->fp);
  852.        interactive = lf->interactive;
  853.        inline_num = lf->inline_num;
  854.        infile_name = lf->name;
  855.        lf_head = lf->prev;
  856.        free((char *)lf);
  857.        return(TRUE);
  858.     }
  859. }
  860.  
  861. /* push onto load_file state stack */
  862. /* essentially, we save information needed to undo the load_file changes */
  863. static void
  864. lf_push(fp)            /* called by load_file */
  865.     FILE *fp;
  866. {
  867.     LFS *lf;
  868.     
  869.     lf = (LFS *)alloc((unsigned long)sizeof(LFS), (char *)NULL);
  870.     if (lf == (LFS *)NULL) {
  871.        if (fp != (FILE *)NULL)
  872.         (void) fclose(fp);        /* it won't be otherwise */
  873.        int_error("not enough memory to load file", c_token);
  874.     }
  875.      
  876.     lf->fp = fp;            /* save this file pointer */
  877.     lf->name = infile_name;    /* save current name */
  878.     lf->interactive = interactive;    /* save current state */
  879.     lf->inline_num = inline_num; /* save current line number */
  880.     lf->prev = lf_head;        /* link to stack */
  881.     lf_head = lf;
  882. }
  883.  
  884. FILE *lf_top()        /* used for reread  vsnyder@math.jpl.nasa.gov */
  885. {   if (lf_head == (LFS *) NULL) return((FILE *)NULL);
  886.     return(lf_head->fp);
  887. }
  888.  
  889.  
  890. load_file_error()            /* called from main */
  891. {
  892.     /* clean up from error in load_file */
  893.     /* pop off everything on stack */
  894.     while(lf_pop())
  895.      ;
  896. }
  897.  
  898. /* find char c in string str; return p such that str[p]==c;
  899.  * if c not in str then p=strlen(str)
  900.  */
  901. #ifdef THINK_C
  902. int instring(char *str, char c)
  903. #else
  904. int
  905. instring(str, c)
  906.     char *str;
  907.     char c;
  908. #endif
  909. {
  910.     int pos = 0;
  911.  
  912.     while (str != NULL && *str != '\0' && c != *str) {
  913.        str++; 
  914.        pos++;
  915.     }
  916.     return (pos);
  917. }
  918.  
  919. show_functions()
  920. {
  921. register struct udft_entry *udf = first_udf;
  922.  
  923.     fprintf(stderr,"\n\tUser-Defined Functions:\n");
  924.  
  925.     while (udf) {
  926.         if (udf->definition)
  927.             fprintf(stderr,"\t%s\n",udf->definition);
  928.         else
  929.             fprintf(stderr,"\t%s is undefined\n",udf->udf_name);
  930.         udf = udf->next_udf;
  931.     }
  932. }
  933.  
  934.  
  935. show_at()
  936. {
  937.     (void) putc('\n',stderr);
  938.     disp_at(temp_at(),0);
  939. }
  940.  
  941.  
  942. disp_at(curr_at, level)
  943. struct at_type *curr_at;
  944. int level;
  945. {
  946. register int i, j;
  947. register union argument *arg;
  948.  
  949.     for (i = 0; i < curr_at->a_count; i++) {
  950.         (void) putc('\t',stderr);
  951.         for (j = 0; j < level; j++)
  952.             (void) putc(' ',stderr);    /* indent */
  953.  
  954.             /* print name of instruction */
  955.  
  956.         fputs(ft[(int)(curr_at->actions[i].index)].f_name,stderr);
  957.         arg = &(curr_at->actions[i].arg);
  958.  
  959.             /* now print optional argument */
  960.  
  961.         switch(curr_at->actions[i].index) {
  962.           case PUSH:    fprintf(stderr," %s\n", arg->udv_arg->udv_name);
  963.                     break;
  964.           case PUSHC:    (void) putc(' ',stderr);
  965.                     disp_value(stderr,&(arg->v_arg));
  966.                     (void) putc('\n',stderr);
  967.                     break;
  968.           case PUSHD1:    fprintf(stderr," %c dummy\n",
  969.                       arg->udf_arg->udf_name[0]);
  970.                     break;
  971.           case PUSHD2:    fprintf(stderr," %c dummy\n",
  972.                       arg->udf_arg->udf_name[1]);
  973.                     break;
  974.           case CALL:    fprintf(stderr," %s", arg->udf_arg->udf_name);
  975.                     if(level < 6) {
  976.                     if (arg->udf_arg->at) {
  977.                         (void) putc('\n',stderr);
  978.                         disp_at(arg->udf_arg->at,level+2); /* recurse! */
  979.                     } else
  980.                         fputs(" (undefined)\n",stderr);
  981.                     } else
  982.                         (void) putc('\n',stderr);
  983.                     break;
  984.           case CALLN:    fprintf(stderr," %s", arg->udf_arg->udf_name);
  985.                     if(level < 6) {
  986.                     if (arg->udf_arg->at) {
  987.                         (void) putc('\n',stderr);
  988.                         disp_at(arg->udf_arg->at,level+2); /* recurse! */
  989.                     } else
  990.                         fputs(" (undefined)\n",stderr);
  991.                     } else
  992.                         (void) putc('\n',stderr);
  993.                     break;
  994.           case JUMP:
  995.           case JUMPZ:
  996.           case JUMPNZ:
  997.           case JTERN:
  998.                     fprintf(stderr," +%d\n",arg->j_arg);
  999.                     break;
  1000.           default:
  1001.                     (void) putc('\n',stderr);
  1002.         }
  1003.     }
  1004. }
  1005.